<?php

class Chocolat_Node
{
	public $data = "";
	public $childs;
	private $text = array();
	
	private $current_line = -1;
	private $node = "/";
	private $current_node_ref;
	
	public function __construct($node = "/")
	{
		$this->node = $node;
	}
	
	private function line($add=1)
	{
		$l = &$this->current_line;
		$l = $l+$add;
		if (!is_string($this->text[$l]))
		{
			$l = -1;
			return false;
		}
		$this->event("line$l");
		return ltrim($this->text[$l]);
	}
	
	public function parse($data,$data_is_url = 0)
	{
		if($data_is_url)
			$text = file_get_contents($data);
		elseif($data != 0)
			$text = $data;
		$this->text = explode("\n",$text); 
		var_dump($this->text);
		
		//Starting to parse
		while(($line = $this->line()) !== false)
		{			
			if		($line{0} == ':')
			{
				list($command,$arg) = explode(':',substr($line,1),2);
				$this->launch_command($command,$arg);
				$this->wfc = 0;
				$this->empties_lines_to_add = 0;
				
			}
			elseif	($line{0} == '>')
			{
				$this->change_namespace(substr($line,1));
				$this->wfc = 0;
				$this->empties_lines_to_add = 0;
			}
			elseif	($line{0} == '.')
			{
				$this->please_return_to[] = $this->current_node;
				$this->change_namespace($this->current_node.'>'.substr($line,1));
				$this->wfc = 0;
				$this->empties_lines_to_add = 0;
			}
			elseif	($line{0} == ';')
			{
				$this->wfc = 1; //Waiting For Command (end of data)
				$this->empties_lines_to_add = 0;
			}
			elseif ((!$this->wfc) && ($line{0} !== '#'))
			{
				if($line{0} == "\\") // '\' est un caractère d'échappement
					$line = substr($line,1);
				if("" == $line) 
				{
					$this->empties_lines_to_add++;
					continue;
				}
				elseif($this->empties_lines_to_add)
				{
					$line = str_repeat("\n",$this->empties_lines_to_add).$line;
					$this->empties_lines_to_add = 0;
				}
				$this->add_line_to_current_ns($line);
				if(($new_ns = array_pop($this->please_return_to)))
				{
					$this->change_namespace($new_ns);
				}
			}
		}
	}
	
	private function change_namespace($path)
	{
		$path = explode('/',$path);
		if($path[0] == null)
		{
			$this->current_node = "";
			$this->current_node_ref = &$this;
		}
		
		
		foreach ($path as $node_name)
		{
			if($node_name)
			{
				$this->current_node .= "/".$node_name;
				if(!$this->current_node_ref->childs->$node_name)
					$this->current_node_ref->childs->$node_name = new Chocolat_Node($this->current_node);
				$this->current_node_ref = &$this->current_node_ref->childs->$node_name;
			}
		}
		$this->event("namespace_changed{$this->current_node}");
	}
	
	private function add_line_to_current_ns($line)
	{
		isset($this->current_node_ref->data)? $line = "\n$line" :null;
		$this->current_node_ref->data .= $line;
	}
	
	/*
	 * A effacer
	 */
	public function __call($func,$args)
	{
		//echo "$func (".implode(",",$args).")";
	}
	
	private function event($event)
	{
		if(isset($this->events[$event]['command']))
		{
			$this->{$this->events[$event]['command']}($this->events[$event]['arg']);
		}
		
		echo "=>event: $event\n";
	}
	
	public function register_event($event,$command = null ,$arg = null)
	{
		$this->events[$event]['command'] = $command;
		$this->events[$event]['arg'] = $arg;
		return true;
	}
	
	public function write($filename = null,$rec_childs = null /*Don't set this*/)
	{
		static $output = ":Chocolat_Version:0.1\n";
		
		$output = ">/\n";
		$output .= $this->data."\n";
		($rec_childs)? $childs = $rec_childs : $childs = $this->childs;
		foreach ($childs as $child)
		{
			//FIXME: Espace en trop
			$output .= "\n>{$child->node}\n{$child->data}\n\n";
			if(!empty($child->childs))
				$this->write(null,$child->childs);
		}
		
		/*(is_writable($filename))? */file_put_contents($filename,$output)/*:null*/;
		 if (!$rec_childs) return $output;
	}
}

///TEST
$choco = new Chocolat_Node();
echo "Parsing ".$argv[1];
echo "\n=======";
$choco->parse(/*getcwd().'/'.*/$argv[1],1);
$choco->write("/tmp/write.choc");

print_r($choco);
echo "\n=======\nEND\n";
